package org.ws.edu.task3.core;

import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Queue;

import org.ws.edu.task3.model.Answer;
import org.ws.edu.task3.model.Question;
import org.ws.edu.task3.model.Test;
import org.ws.edu.task3.model.Type;

public class TestManager {
	private final String folderPath = "./tests";
	private String nameTest = null;
	private List<Answer> answer = null;
	private List<Answer> rightAnswer = null;
	private List<Question> questions = null;
	private Question curQuestion = null;
	private TestLoader testLoader = null;
	private Test curTest = null;
	private ListIterator<Question> iter = null;
	private Type type = null;
	double rezBal = 0.0;
	private Queue<Integer> noAnswers = new LinkedList<Integer>();
	private int rAnsw = 0;
	private int allAnsw = 0;
	private boolean second = false;

	public TestManager() {
		testLoader = TestLoader.newInstance(folderPath);
	}

	public String[] getValidTest() {
		return testLoader.getAvailableTestNames();
	}

	public String[] getInvalidTest() {
		return testLoader.getInvalidTestNames();
	}

	public String getNameTest() {
		return nameTest;
	}

	public void setNameTest(String nameTest) {
		curTest = testLoader.getTest(nameTest);
		questions = curTest.getQuestions();
		allAnsw = questions.size();
		rAnsw = 0;
		iter = questions.listIterator();
		setType(curTest.getType());
		noAnswers.clear();
		second = false;
		this.nameTest = nameTest;
		rezBal = 0;
	}

	public Type getType() {
		return type;
	}

	public void setType(Type type) {
		this.type = curTest.getType();
	}

	public boolean hasPassQuestion() {
		if (!noAnswers.isEmpty()) {
			second = true;
			iter = questions.listIterator();
			return true;
		}
		return false;
	}

	public Question getCurQuestion() {
		// TODO: Что будет если метод вызвать 2 раза?
		setCurQuestion(iter.next());
		return curQuestion;
	}

	public void setCurQuestion(Question curQuestion) {
		rightAnswer = curQuestion.getRightAnswers();
		this.curQuestion = curQuestion;
	}

	public List<Answer> getAnswer() {
		return answer;
	}

	public void setAnswer(List<Answer> userAnswer) {
		if (userAnswer.size() == 0) {
			for (int i = 0; i <= questions.size(); i++) {
				if (questions.get(i).getName().equals(curQuestion.getName())) {
					noAnswers.offer(i);
					break;
				}
			}
			return;
		}
		switch (type) {
			case SINGLE_ANSWER_TEST:
			case MULTI_ANSWER_TEST:
				rezBal += calcType1(userAnswer);
				break;
			case SCALES:
				rezBal += calcType2(userAnswer);
				break;
		}
		this.answer = userAnswer;
	}

	public String getResult() {
		switch (type) {
			case SINGLE_ANSWER_TEST:
			case MULTI_ANSWER_TEST:
				return "Вы ответили правильно на " + rAnsw + " из " + allAnsw + " возможных";
			case SCALES:
				return curTest.getResult().get(getKey(rezBal));
		}
		return "no Result";
	}

	public double calcType1(List<Answer> userAnswer) {
		rightAnswer = curQuestion.getRightAnswers();
		double rez = 0, factors = 0;
		int i, j, uSize = userAnswer.size(), rSize = rightAnswer.size();
		for (i = 0; i < rSize; i++) {
			factors += rightAnswer.get(i).getFactor();
			for (j = 0; j < uSize; j++) {
				if (rightAnswer.get(i).getName().equals(userAnswer.get(j).getName())) {
					rez += userAnswer.get(i).getFactor();
				}
			}

		}
		if (rez == factors)
			rAnsw++;
		return rez;
	}

	public double calcType2(List<Answer> userAnswer) {
		double rez = 0;
		answer = curQuestion.getAllAnswers();
		int i, size = answer.size();
		for (i = 0; i < size; i++) {
			if (answer.get(i).getName().equals(userAnswer.get(0).getName())) {
				return rez += answer.get(i).getFactor();
			}

		}
		return 0;
	}

	public Question getNextQuestion() {
		if (second && !noAnswers.isEmpty()) {
			int a = noAnswers.poll();
			while (iter.hasNext() && iter.nextIndex() != a) {
				iter.next();
			}
		}
		return getCurQuestion();
	}

	public boolean hasMoreQuestion() {
		if (second && noAnswers.isEmpty()) {
			while (iter.hasNext()) {
				// TODO: что это? опять же что будет если вызову дважды
				iter.next();
			}
		}
		return iter.hasNext();
	}
//TODO  javadoc?
	public Integer getKey(Double rezBal) {
		Integer key = 0;
		int i = 0;
		String str = null, str2 = "";
		str = String.valueOf(rezBal);
		while (str.charAt(i) != '.') {
			str2 += str.charAt(i);
			i++;
		}
		key = Integer.valueOf(str2);
		while (!curTest.getResult().containsKey(key)) {
			key--;
		}
		return key;
	}
}